package com.ayf.payment.game.api.channel.ehb.handler;

import com.alibaba.fastjson.JSONObject;
import com.ayf.payment.game.api.channel.BaseHandler;
import com.ayf.payment.game.api.channel.ehb.exception.InvalidEncryptedKeyException;
import com.ayf.payment.game.api.channel.ehb.response.RealTimePayOrderStatusEnum;
import com.ayf.payment.game.api.channel.ehb.response.SinglePayBalanceQueryRes;
import com.ayf.payment.game.api.channel.ehb.response.SinglePayOrderCreateRes;
import com.ayf.payment.game.api.channel.ehb.util.AESUtil;
import com.ayf.payment.game.api.channel.ehb.util.EhbUtil;
import com.ayf.payment.game.api.channel.ehb.util.EncryptedRandomKey;
import com.ayf.payment.game.api.channel.ehb.util.RSA;
import com.ayf.payment.game.api.dto.platform.SubstitutePayConfigDTO;
import com.ayf.payment.game.api.dto.platform.pay.EhbPayConfigParamVO;
import com.ayf.payment.game.api.service.platform.SubstitutePayConfigService;
import com.ayf.payment.game.api.type.MerchantPayOrderStatusEnum;
import com.ayf.payment.game.api.utils.BigDecimalUtil;
import com.swwx.charm.commons.lang.utils.LogPortal;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.net.SocketTimeoutException;
import java.util.HashMap;
import java.util.Map;

@Component("EHB_PAYHandler")
public class EhbPayHandler implements BaseHandler {

    // 代付订单创建
    private static final String PAY_ORDER_CREATE = "v1/single/pay/create";
    // 代付订单查询
    public static final String PAY_ORDER_QUERY = "v1/single/pay/query";
    public static final String PAY_BALANCE_QUERY = "v1/single/pay/balance";
    @Autowired
    private SubstitutePayConfigService substitutePayConfigService;

    @Override
    public JSONObject orderCreate(JSONObject inputParam) {
        JSONObject resJson = new JSONObject();
        String merchantOrderNo = inputParam.getString("merchant_order_no");
        resJson.put("merchantOrderNo",merchantOrderNo);
        resJson.put("status", MerchantPayOrderStatusEnum.PAY_PROCESSING.getStatus());

        String traceId = inputParam.getString("traceId");
        Integer substitutePayConfigId = inputParam.getInteger("substitutePayConfigId");
        SubstitutePayConfigDTO substitutePayConfigDTO= substitutePayConfigService.getSubstitutePayConfigById(substitutePayConfigId);
        EhbPayConfigParamVO ehbPayConfigParamVO = substitutePayConfigDTO.getEhbPayConfigParamVO();
        String orderCreateUrl = ehbPayConfigParamVO.getChannelUrl();
        if (!orderCreateUrl.endsWith("/")){
            orderCreateUrl=orderCreateUrl.concat("/");
        }
        orderCreateUrl=orderCreateUrl.concat(PAY_ORDER_CREATE);
        try {
            JSONObject orderReqMap = new JSONObject();
            // 商户系统内部订单号，要求64个字符内，只能是数字、大小写字母_-|* 且在同一个商户号下唯一
            orderReqMap.put("merchant_order_no",merchantOrderNo);
            // 订单总金额，单位为分
            orderReqMap.put("amount", BigDecimalUtil.yuanToFen(inputParam.getBigDecimal("amount")));

            // 获取加密的原始密码
            String pwd = EncryptedRandomKey.getEncryptedRandomKey();
            // 原账号数值 银行卡号或者支付宝账号
            String originAccountNo = inputParam.getString("account_no");
            // 加密之后的账号数值
            String aesEncryptedAccountNo= AESUtil.aesEncrypt(originAccountNo,pwd);
            // 必须进行AES加密，此数值是银行卡号或者支付宝账号
            orderReqMap.put("account_no",aesEncryptedAccountNo);
            // 账号名称 此数值是银行卡号或者支付宝账号对应的户名
            orderReqMap.put("account_name",inputParam.getString("account_name"));

            // 使用商户私钥对加密密码的原文进行加密
            String rsaEncryptedPwd = RSA.encrypt(pwd,ehbPayConfigParamVO.getMerchantPriKey());
            // 临时密钥 敏感字段加密时使用的密钥，注意:RSA加密之前密钥原文固定16个字节
            orderReqMap.put("encrypted_key",rsaEncryptedPwd);

            // 交易描述，要求300个字符内，不能包含特殊字符:英文逗号，注意：下载对账单会返回此字段数据
            orderReqMap.put("description",inputParam.getString("description"));
            // 交易发起时间时间，格式为yyyyMMddHHmmss
            orderReqMap.put("apply_time",inputParam.getString("apply_time"));
            // 账号类型：0-对公 1-对私借记卡 2-支付宝 3-爱游宝
            Integer payType = inputParam.getInteger("account_type");
            Integer accountType = 1;
            if (payType==1){
                accountType = 2;
            } else if (payType==2){
                accountType = 3;
            }
            orderReqMap.put("account_type",accountType);
            // 银行名称 账号类型为0时，必填
            orderReqMap.put("bank_name",inputParam.getString("bank_name"));
            orderReqMap.put("open_province",inputParam.getString("bank_province"));
            orderReqMap.put("open_city",inputParam.getString("bank_city"));

            String bankCode = getBankCode(traceId, inputParam.getString("bank_name"));
            orderReqMap.put("bank_code",bankCode);
            // 异步通知地址
            orderReqMap.put("notify_url",ehbPayConfigParamVO.getNotifyUrl());
            String jsonReqData = orderReqMap.toJSONString();
            LogPortal.info("{} 代付下单请求参数:{}",traceId,jsonReqData);
            SinglePayOrderCreateRes res = EhbUtil.request(traceId,orderCreateUrl,jsonReqData,ehbPayConfigParamVO, SinglePayOrderCreateRes.class);
            if (res.isReqSuccessFlag()){ // 请求成功
                if (res.isSuccess()){ // 业务处理成功
                    if (RealTimePayOrderStatusEnum.FAIL.equals(res.getStatus())){ // 代付订单受理失败，需要重新发起代付
                        resJson.put("status", MerchantPayOrderStatusEnum.PAY_FAIL.getStatus());
                    }
                    resJson.put("channelOrderNo",res.getOrderNo());
                } else {
                    resJson.put("status", MerchantPayOrderStatusEnum.PAY_FAIL.getStatus());
                    resJson.put("failReason",res.getFailRason());
                }
            } else {
                resJson.put("status", MerchantPayOrderStatusEnum.PAY_FAIL.getStatus());
                resJson.put("failReason","支付通道系统繁忙，请稍后重试");
            }
        } catch (SocketTimeoutException e) {
            LogPortal.error("{} 代付下单 通道响应超时 商户订单号:{}",traceId,merchantOrderNo);
        } catch (InvalidEncryptedKeyException e) {
            LogPortal.error("{} 代付下单失败，参数账号加密错误 商户订单号:{}",traceId,e.getClass().getName(),merchantOrderNo);
            resJson.put("status", MerchantPayOrderStatusEnum.PAY_FAIL.getStatus());
            resJson.put("failReason","账号加密错误，请联系技术支持");
            return resJson;
        } catch (Exception e) {
            LogPortal.error("{} 代付下单失败，发生{}异常 商户订单号:{}",traceId,e.getClass().getName(),merchantOrderNo);
            resJson.put("status", MerchantPayOrderStatusEnum.PAY_FAIL.getStatus());
            resJson.put("failReason","系统繁忙，请稍后重试");
            return resJson;
        }
        LogPortal.info("{} 代付下单 商户订单号:{} 响应报文:{}",traceId,merchantOrderNo,resJson.toJSONString());
        return resJson;
    }

    @Override
    public JSONObject orderQuery(JSONObject inputParam) {
        JSONObject resJson = new JSONObject();
        String merchantOrderNo = inputParam.getString("merchant_order_no");
        resJson.put("merchantOrderNo",merchantOrderNo);
        resJson.put("status", MerchantPayOrderStatusEnum.PAY_PROCESSING.getStatus());

        String traceId = inputParam.getString("traceId");
        Integer substitutePayConfigId = inputParam.getInteger("substitutePayConfigId");
        SubstitutePayConfigDTO substitutePayConfigDTO= substitutePayConfigService.getSubstitutePayConfigById(substitutePayConfigId);
        EhbPayConfigParamVO ehbPayConfigParamVO = substitutePayConfigDTO.getEhbPayConfigParamVO();
        String orderCreateUrl = ehbPayConfigParamVO.getChannelUrl();
        if (!orderCreateUrl.endsWith("/")){
            orderCreateUrl=orderCreateUrl.concat("/");
        }
        orderCreateUrl=orderCreateUrl.concat(PAY_ORDER_QUERY);
        try {
            JSONObject orderReqMap = new JSONObject();
            orderReqMap.put("merchant_order_no",merchantOrderNo);
            String jsonReqData = orderReqMap.toJSONString();
            LogPortal.info("{} 代付下单查询请求参数:{}",traceId,jsonReqData);
            SinglePayOrderCreateRes res = EhbUtil.request(traceId,orderCreateUrl,jsonReqData,ehbPayConfigParamVO, SinglePayOrderCreateRes.class);
            if (res.isReqSuccessFlag()) { // 请求成功
                if (res.isSuccess()) { // 业务处理成功
                    if (RealTimePayOrderStatusEnum.FAIL.equals(res.getStatus())) { // 代付订单受理失败，需要重新发起代付
                        resJson.put("status", MerchantPayOrderStatusEnum.PAY_FAIL.getStatus());
                    } else if (RealTimePayOrderStatusEnum.SUCCESS.equals(res.getStatus())) { // 代付订单受理失败，需要重新发起代付
                        resJson.put("status", MerchantPayOrderStatusEnum.PAY_SUCCESS.getStatus());
                    }
                    resJson.put("channelOrderNo", res.getOrderNo());
                }
            }
        } catch (SocketTimeoutException e) {
            LogPortal.error("{} 代付下单查询 通道响应超时 商户订单号:{}",traceId,merchantOrderNo);
        }  catch (Exception e) {
            LogPortal.error("{} 代付下单查询失败，发生{}异常 商户订单号:{}",traceId,e.getClass().getName(),merchantOrderNo);
        }
        LogPortal.info("{} 代付下单查询 商户订单号:{} 响应报文:{}",traceId,merchantOrderNo,resJson.toJSONString());
        return resJson;
    }

    @Override
    public JSONObject balanceQuery(JSONObject inputParam) {
        JSONObject resJson = new JSONObject();
        String traceId = inputParam.getString("traceId");
        String bankName = inputParam.getString("bankName");
        String bankCode = getBankCode(traceId, bankName);
        if (StringUtils.isEmpty(bankCode)) {
            resJson.put("status", "2");
            return resJson;
        }
        Integer substitutePayConfigId = inputParam.getInteger("substitutePayConfigId");
        SubstitutePayConfigDTO substitutePayConfigDTO = substitutePayConfigService.getSubstitutePayConfigById(substitutePayConfigId);
        EhbPayConfigParamVO ehbPayConfigParamVO = substitutePayConfigDTO.getEhbPayConfigParamVO();
        String orderCreateUrl = ehbPayConfigParamVO.getChannelUrl();
        if (!orderCreateUrl.endsWith("/")) {
            orderCreateUrl = orderCreateUrl.concat("/");
        }
        orderCreateUrl = orderCreateUrl.concat(PAY_BALANCE_QUERY);

        Map<String, Object> orderReqMap = new HashMap<String, Object>();
        // 商户系统内部订单号，要求64个字符内，只能是数字、大小写字母_-|* 且在同一个商户号下唯一
        orderReqMap.put("merchant_order_no", EncryptedRandomKey.getEncryptedRandomKey());
        String reqStr = JSONObject.toJSONString(orderReqMap);
        System.out.println("代付余额查询请求参数:" + reqStr);
        try {
            SinglePayBalanceQueryRes res = EhbUtil.request(traceId, orderCreateUrl, reqStr, ehbPayConfigParamVO,
                    SinglePayBalanceQueryRes.class);
//            System.out.println("代付余额查询响应报文:\n" + res);
            if (res.isReqSuccessFlag()) { // 请求成功
//                if (res.isSuccess()) { // 业务处理成功
                resJson.put("status", "1");
                resJson.put("balance", res.getBalanceAmt());
//                }
            } else {
                resJson.put("status", "0");
            }
        } catch (SocketTimeoutException e) {
            LogPortal.error("{} 代付余额查询 通道响应超时 渠道商户id:{}", traceId, ehbPayConfigParamVO.getChannelMerchantId());
        } catch (Exception e) {
            LogPortal.error("{} 代付余额查询失败，发生{}异常  渠道商户id:{}", traceId, e.getClass().getName(), ehbPayConfigParamVO.getChannelMerchantId());
        }

        return resJson;
    }

    private String getBankCode(String traceId, String bankName) {
        if (bankName.contains("支付宝")) {
            return "ZFB";
        } else if (bankName.contains("爱游宝")) {
            return "AYB";
        } else if (bankName.contains("工商银行")) {
            return "ICBC";
        } else if (bankName.contains("农业银行")) {
            return "ABC";
        } else if (bankName.contains("广东南粤银行")) {
            return "GDNB";
        } else if (bankName.contains("建设银行")) {
            return "CCB";
        } else if (bankName.contains("厦门国际银行")) {
            return "XIB";
        } else if (bankName.contains("民生银行")) {
            return "CMBC";
        } else if (bankName.contains("兴业银行")) {
            return "CIB";
        } else if (bankName.contains("交通银行")) {
            return "BCM";
        } else if (bankName.contains("广发银行")) {
            return "GDB";
        } else if (bankName.contains("平安银行")) {
            return "PAB";
        } else if (bankName.contains("天津银行")) {
            return "TJCB";
        } else if (bankName.contains("内蒙古银行")) {
            return "BOIMC";
        } else if (bankName.contains("郑州银行")) {
            return "CBZZ";
        } else if (bankName.contains("哈尔滨银行")) {
            return "HBCB";
        } else if (bankName.contains("广州银行")) {
            return "GZCB";
        } else if (bankName.contains("吉林银行")) {
            return "JLCB";
        } else if (bankName.contains("长安银行")) {
            return "CAB";
        } else if (bankName.contains("湖北银行")) {
            return "HBC";
        } else if (bankName.contains("烟台银行")) {
            return "YTCB";
        } else if (bankName.contains("中原银行")) {
            return "ZYB";
        } else if (bankName.contains("光大银行")) {
            return "CEB";
        } else if (bankName.contains("华夏银行")) {
            return "HXB";
        } else if (bankName.contains("宁波银行")) {
            return "NBCB";
        } else if (bankName.contains("农业银行")) {
            return "ABC";
        } else if (bankName.contains("中国银行")) {
            return "BOC";
        } else if (bankName.contains("建设银行")) {
            return "CCB";
        } else if (bankName.contains("交通银行")) {
            return "BCOM";
        } else if (bankName.contains("招商银行")) {
            return "CMB";
        } else if (bankName.contains("广东发展银行")) {
            return "GDB";
        } else if (bankName.contains("中信银行")) {
            return "CITIC";
        } else if (bankName.contains("浦发银行")||bankName.contains("浦东发展")) {
            return "SPDB";
        }  else if (bankName.contains("邮政储蓄")) {
            return "PSBC";
        } else if (bankName.contains("包商银行")) {
            return "BSB";
        } else if (bankName.contains("浙江网商银行")) {
            return "SWB";
        }else if (bankName.contains("龙江银行")) {
            return "LJCB";
        } else {
            LogPortal.error("[{}]爱游付代付银行类别匹配错误[{}]", traceId, bankName);
            return null;
        }
    }
}
